home *** CD-ROM | disk | FTP | other *** search
- /* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Cumulate Draw SVG Renderer.
- *
- * The Initial Developer of the Original Code is Cumulate Labs Inc.
- * Portions created by Cumulate Labs Inc. are Copyright (C) 2006-2007
- * Cumulate Labs Inc. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the terms of
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
- /**
- *AbstractRenderer is the parent class for VMLRenderer and SVGRenderer. The intent is to provide
- * a high level api for shape manipulation and hide the details in specific renderers.
- **/
-
- /**
- * constructor, do not invoke this directly, used by renderers to subclass.
- */
-
- function AbstractRenderer() {
-
- };
-
- AbstractRenderer.prototype.init = function(elem) {
- this.VML_SVG_NAMESPACE="VML_SVG";
- };
- ///////////////////////////////////////BEGIN OVERRIDDEN METHODS///////////////////////////////////////
- /**
- * return the bounds of the shape
- * @see VMLRenderer.bounds
- * @see SVGRenderer.bounds
- */
- AbstractRenderer.prototype.bounds = function(shape) { return { x:0, y:0, width:0, height: 0 }; };
- /**
- * initial call to create a shape (but not connector, for connectors see createLine)
- */
- AbstractRenderer.prototype.create = function(shape, fillColor, lineColor, lineWidth, left, top, width, height,opacity,gradient) {};
- /**
- * remove a node
- */
- AbstractRenderer.prototype.remove = function(shape) {};
- /**
- * move a shape to new left and to location
- */
- AbstractRenderer.prototype.move = function(shape, left, top) {};
- AbstractRenderer.prototype.fineMove = function(shape, move,isHorizontal) {};
- /**
- * get the underlying shpae which cause this event
- */
- AbstractRenderer.prototype.getShapeFromEventSource=function(source){};
- /**
- *get from x for a valid connector
- **/
- AbstractRenderer.prototype.getConnectorFromX=function(shape){}
- /**
- *get from y for a valid connector
- **/
- AbstractRenderer.prototype.getConnectorFromY=function(shape){}
- /**
- *get to x for a valid connector
- **/
- AbstractRenderer.prototype.getConnectorToX=function(shape){}
- /**
- *get to y for a valid connector
- **/
-
- AbstractRenderer.prototype.getConnectorToY=function(shape){}
-
- /**
- *set shape width
- **/
- AbstractRenderer.prototype.setWidth=function(shape,width){}
- /**
- *set shape height
- **/
- AbstractRenderer.prototype.setHeight=function(shape,height){}
- /**
- *set shape x (left)
- **/
- AbstractRenderer.prototype.setX=function(shape,left){}
- /**
- *set shape Y(top)
- **/
- AbstractRenderer.prototype.setY=function(shape,top){
- }
-
- /**
- *get all shape objects (not including connectors)!
- **/
- AbstractRenderer.prototype.getAllShapes=function(doc){}
- /**
- *get all connectors (but not shapes)
- **/
- AbstractRenderer.prototype.getAllConnectors=function(doc){
- }
- /**
- *Only used during draw, for general resize using handles see resizeWidth, resizeHeight
- **/
- AbstractRenderer.prototype.resize = function(shape, fromX, fromY, toX, toY) {};
- /**
- * @see vmlrenderer#editCommand
- * @see svgrenderer#editCommand
- */
- AbstractRenderer.prototype.editCommand = function(shape, cmd, value) {};
- /**
- * @see vmlrenderer#queryCommand
- * @see svgrenderer#queryCommand
- *
- */
- AbstractRenderer.prototype.queryCommand = function(shape, cmd) {};
- AbstractRenderer.prototype.showTracker = function(shape) {};
- AbstractRenderer.prototype.updateTracker = function(shape) {};
- AbstractRenderer.prototype.getMarkup = function() { return null; };
- AbstractRenderer.prototype.fineRotateSelection=function(shape,angle){};
- AbstractRenderer.prototype.rotate=function(shape,angle){};
- AbstractRenderer.prototype.setCursor=function(shape,cursor){};
- AbstractRenderer.prototype.setFillColor=function(shape,fillColor){};
- AbstractRenderer.prototype.setShapeText=function(shape,text,font,override,zoom){};
- AbstractRenderer.prototype.getShapeText=function(shape){};
- AbstractRenderer.prototype.clearShapeText=function(shape){};
- AbstractRenderer.prototype.sendToBack=function(shape){};
- AbstractRenderer.prototype.bringToFront=function(shape){};
- AbstractRenderer.prototype.updateZIndex=function(shape){};
- AbstractRenderer.prototype.setLineStyle=function(connector,style){};
- AbstractRenderer.prototype.getLineStyle=function(connector){};
- AbstractRenderer.prototype.setStrokeWidth=function(shape,value){};
- AbstractRenderer.prototype.getStrokeWidth=function(shape){};
-
- AbstractRenderer.prototype.isConnector=function(shape){};
- //line draw functions
- AbstractRenderer.prototype.createLine=function(mode,lineColor,lineWidth,left,top,width,height){};
- AbstractRenderer.prototype.moveLine=function(line,toX,toY,isFrom){};//isfrom indicates which end is being moved
- AbstractRenderer.prototype.moveLinePoint=function(line,toX,toY,isFrom){};//isfrom indicates which end is being moved
- AbstractRenderer.prototype.moveLineWithShape=function(shape){};
- AbstractRenderer.prototype.showConnectionPoints=function(shape){};
- AbstractRenderer.prototype.connectLine=function(shape,line,toOrFrom){};
- /**
- * this method is implemented only in the vml renderer to fix the polyline points issue in IE
- **/
- AbstractRenderer.prototype.savePolyLinePaths=function(){};
-
- AbstractRenderer.prototype.appendPageAttribute=function(div,att){};
- AbstractRenderer.prototype.getRealData=function(){};
- AbstractRenderer.prototype.updateRotation=function(shape){}
- /**
- * return all the subshapes for a given shape
- * @param shape
- * @return list of all subshapes
- */
- AbstractRenderer.prototype.getAllSubShapes=function(shape){};
- /**
- *this method will return the actual subject of a shape, the subject could either be a path or line,polyline in case
- of connectors, this assumes that the shape has only one subject, if a shape is comples with multiple sub-shapes
- * see getAllSubshapes.
- **/
- AbstractRenderer.prototype.getShapeSubject=function(shape){};
-
- ////////////////////////////////////END OVERRIDDEN FUNCTIONS//////////////////////////////////////////
-
- /**
- *resize shape width, this is a hacked method to compensate for shape movement during rotated resize. Ideally
- * we should do some combination of translate rotate and translate back
- * @param theshape
- * @param current mouse X
- * @param current mouse y
- * @param initial mouse down x
- * @param initia mouse down x
- * @param prev width (before resize started)
- * @param is right or left stretch
- *
- **/
-
- AbstractRenderer.prototype.resizeWidth = function(shape,snappedX,snappedY, mouseDownX,mouseDownY,prevWidth,isRightStretch) {
- var distanceA=((snappedX-mouseDownX)*(snappedX-mouseDownX))+((snappedY-mouseDownY)*(snappedY-mouseDownY));
- distanceA=Math.sqrt(distanceA);
- var bounds=this.bounds(shape);
- var rotation=bounds.rotation;
- if(!rotation||rotation=="undefined"){
- rotation=0;
- }
- rotation =rotation%360;
- var snpX=(snappedX*Math.cos((Math.PI/180)*(-rotation)))-(snappedY*Math.sin((Math.PI/180)*(-rotation)));
- var mouseX=(mouseDownX*Math.cos((Math.PI/180)*(-rotation)))-(mouseDownY*Math.sin((Math.PI/180)*(-rotation)));
- if(snpX<mouseX&&(isRightStretch)){
- distanceA=-distanceA;
- }
- else if(snpX>mouseX&&(!isRightStretch)){
- distanceA=-distanceA;
- }
-
- var width=prevWidth;
-
- width=(width*1)+distanceA;
- if(width<1){
- return false;
- }
-
- var obj=null;
- if(isRightStretch)
- obj=this.getRotatedPoint(bounds.x,bounds.y,bounds);
- else
- obj=this.getRotatedPoint((bounds.x*1)+(bounds.width*1),(bounds.y*1)+(bounds.height*1),bounds);
-
- this.setWidth(shape,width);
- var newBounds=this.bounds(shape);
- var newObj=null;
- if(isRightStretch)
- newObj=this.getRotatedPoint(newBounds.x,newBounds.y,newBounds);
- else
- newObj=this.getRotatedPoint((newBounds.x*1)+(newBounds.width*1),(newBounds.y*1)+(newBounds.height*1),newBounds);
- var xFactor=Math.round(obj.x)-Math.round(newObj.x);
- var yFactor=Math.round(obj.y)-Math.round(newObj.y);
-
- this.setX(shape,(newBounds.x*1)+xFactor);
- this.setY(shape,(newBounds.y*1)+yFactor);
- this.updateRotation(shape);
-
- };
-
-
- /**
- *resize height
- * @param theshape
- * @param current mouse X
- * @param current mouse y
- * @param initial mouse down x
- * @param initia mouse down x
- * @param prev height (before resize started)
- * @param is top or bottom stretch
- **/
- AbstractRenderer.prototype.resizeHeight = function(shape, snappedX,snappedY, mouseDownX,mouseDownY,prevHeight,isBottomStretch) {
- var distanceA=((snappedY-mouseDownY)*(snappedY-mouseDownY))+((snappedX-mouseDownX)*(snappedX-mouseDownX));
- distanceA=Math.sqrt(distanceA);
- var bounds=this.bounds(shape);
- var rotation=bounds.rotation;
- if(!rotation||rotation=="undefined"){
- rotation=0;
- }
- rotation =rotation%360;
- var snpY=(snappedY*Math.cos((Math.PI/180)*(-rotation)))+(snappedX*Math.sin((Math.PI/180)*(-rotation)));
- var mouseY=(mouseDownY*Math.cos((Math.PI/180)*(-rotation)))+(mouseDownX*Math.sin((Math.PI/180)*(-rotation)));
- if(snpY<mouseY&&isBottomStretch){
- distanceA=-distanceA;
- }
- else if(snpY>mouseY&&(!isBottomStretch)){
- distanceA=-distanceA;
- }
- var height=prevHeight;
- height=(height*1)+distanceA;
- if(height<1){
- return false;
- }
- var obj=null;
- if(isBottomStretch)
- obj=this.getRotatedPoint(bounds.x,bounds.y,bounds);
- else
- obj=this.getRotatedPoint((bounds.x*1)+(bounds.width*1),(bounds.y*1)+(bounds.height*1),bounds);
-
- this.setHeight(shape,height);
- var newBounds=this.bounds(shape);
- var newObj=null;
- if(isBottomStretch)
- newObj=this.getRotatedPoint(newBounds.x,newBounds.y,newBounds);
- else
- newObj=this.getRotatedPoint((newBounds.x*1)+(newBounds.width*1),(newBounds.y*1)+(newBounds.height*1),newBounds);
- var xFactor=Math.round(obj.x)-Math.round(newObj.x);
- var yFactor=Math.round(obj.y)-Math.round(newObj.y);
- //alert("xFactor:"+xFactor+"yFactor:"+yFactor);
- this.setX(shape,(newBounds.x*1)+xFactor);
- this.setY(shape,(newBounds.y*1)+yFactor);
- this.updateRotation(shape);
-
-
-
- };
-
- /**
- * move the complete line segment, used for drag. Moves both ends of the line/polyline/curve and control points
- * if any
- * @param shape
- * @param original shape bounds
- * @param {int} deltaX
- * @param {int} deltaY
- */
- AbstractRenderer.prototype.moveCompleteLine=function(shape,bounds,deltaX,deltaY){
- if(!this.isConnector(shape)){
- return;
- }
- var type=bounds.type;
- var fromX=(bounds.x*1)+deltaX;
- var fromY=(bounds.y*1)+deltaY;
- var toX=(bounds.x2*1)+deltaX;
- var toY=(bounds.y2*1)+deltaY;
- this.moveLine(shape,fromX,fromY,true);
- this.moveLine(shape,toX,toY,false);
- if(type=='curve-line'){
- var controlX=(bounds.controlX*1)+deltaX;
- var controlY=(bounds.controlY*1)+deltaY;
- var controlX2=(bounds.controlX2*1)+deltaX;
- var controlY2=(bounds.controlY2*1)+deltaY;
- this.setControl1(shape,controlX,controlY);
- this.setControl2(shape,controlX2,controlY2);
- }
-
- }
-
- /**
- * get the center point location for a connector, for line and ortholine:
- * centerpoint=(x2+x1/2),(y2+y1/2)
- * For curved connectors, the center point is (centerControlPoints+centerEndPoints)/2
- * @return {object} with attributes x and y
- */
- AbstractRenderer.prototype.getConnectorCenterPoint=function(shape){
- var bounds=this.bounds(shape);
- var type=this.getConnectorType(shape);
- var obj=new Object();
- if(type=='line'){
- obj.x=((bounds.x*1)+(bounds.x2*1))/2;
- obj.y=((bounds.y*1)+(bounds.y2*1))/2;
- }
- else if (type=='curve-line'){
- var controlCenterX=((bounds.controlX*1)+(bounds.controlX2*1))/2;
- var controlCenterY=((bounds.controlY*1)+(bounds.controlY2*1))/2;
- var pointsCenterX=((bounds.x*1)+(bounds.x2*1))/2;
- var pointsCenterY=((bounds.y*1)+(bounds.y2*1))/2;
- obj.x=((controlCenterX*1)+(pointsCenterX))/2;
- obj.y=((controlCenterY*1)+(pointsCenterY))/2;
- }
- else if (type=='ortho-line'){
- var bounds=this.getOrthoLineCenterSegment(shape);
- obj.x=((bounds.x*1)+(bounds.x2*1))/2;
- obj.y=((bounds.y*1)+(bounds.y2*1))/2;
- }
- return obj;
- }
- /**
- * TODO: should be renamed to getTextSize since it returns the height and width of any text, not just
- * connector text
- * @param theshape
- * @param thetext
- * @param current zoomfactor
- * @param current font (if any)
- */
- AbstractRenderer.prototype.getConnectorTextSize=function(shape,editText,zoom,oldFont){
-
- var text=null;
- var font=oldFont;
- if(editText)
- text=editText;
- else
- text=this.getShapeText(shape);
- if(font==null){
- font=this.getFont(shape);
- }
- //if no font, use default
- if(font.size.length==0){
- this.fillUpFont(font);
- font.size=font.size*zoom;
- }
-
-
-
- //first calculate the number of lines
- var numLines=1;
- var last = 0;
- while ( true ) {
- last = text.indexOf("\n", last+1);
- if ( last == -1 ) break;
- numLines ++;
- }
- // if(numLines>1)numLines--;
- //height will be numlines*2*font
- var height=numLines*font.size*1.5;
- //width will be the longest line +20
- var lines=text.split("\n");
- var highWidth=50;
- for (var i=0;i<lines.length;i++){
- if(lines[i].length*font.size/2>highWidth)
- highWidth=lines[i].length*font.size/2;
- }
- highWidth=(highWidth*1)+10;
- var obj=new Object();
- obj.width=highWidth;
- obj.height=height;
- return obj;
- }
-
- AbstractRenderer.prototype.calculateOrthoLinePath=function(shape,fromX,fromY,toX,toY){
- var points1=this.getClearancePoints(shape,fromX,fromY,toX,toY,true);
- var points2=this.getClearancePoints(shape,toX,toY,points1[points1.length-1].x,points1[points1.length-1].y,false);
- var x1=points1[points1.length-1].x;
- var y1=points1[points1.length-1].y;
- var x2=points2[points2.length-1].x;
- var y2=points2[points2.length-1].y;
- var obj=new Object();
-
- obj.x=x1;
- obj.y=y2;
-
- points1[points1.length]=obj;
- for(var i=points2.length-1;i>=0;i--){
- points1[points1.length]=points2[i];
-
- }
- var path="";
- for (var i=0;i<points1.length;i++){
- path+=points1[i].x+",";
- path+=points1[i].y+",";
-
- }
- return path;
-
-
-
- }
- /**
- *get the clearance points for a given shape
- **/
- AbstractRenderer.prototype.getClearancePoints=function(line,fromX,fromY,toX,toY,isFrom){
- //debugger;
- var TOP=0;
- var RIGHT=1;
- var BOTTOM=2;
- var LEFT=3;
- var CONSTANT=12;
- var array=new Array();
- var obj=new Object();
- obj.x=fromX;
- obj.y=fromY;
- array[array.length]=obj;
- var shapeProps=this.getConnectionShape(line,isFrom);
- if(!$(shapeProps.shapeid)){
-
- return array;
- }
-
- var shape=$(shapeProps.shapeid);
- var bounds=this.bounds(shape);
- var loc=this.getConnectionPointLocation(shape,shapeProps.shapepoint,bounds);//implement
- var clear=this.getRotatedClearancePoints(bounds,loc,CONSTANT);//implement,clear[0] will be first clearance, clear [1] will be second clearance
- var orient=(parseInt((bounds.rotation)/90)+(loc*1))%4;
- //add basic clearance
- obj=new Object();
- if(orient==TOP){
- var factor=Math.abs(fromY-toY)/2;
- if(factor<CONSTANT)factor=CONSTANT;
- obj.y=array[array.length-1].y-CONSTANT;//replace this with constant!!!
- obj.x=array[array.length-1].x;
- }
- else if(orient==BOTTOM){
- var factor=Math.abs(fromY-toY)/2;
- if(factor<CONSTANT)factor=CONSTANT;
- obj.y=array[array.length-1].y+CONSTANT;//replace this with constant!!!
- obj.x=array[array.length-1].x;
- }
- else if(orient==RIGHT){
- var factor=Math.abs(fromX-toX)/2;
- if(factor<CONSTANT)factor=CONSTANT;
- obj.x=array[array.length-1].x+CONSTANT;//replace this with constant!!!
- obj.y=array[array.length-1].y;
- }
- else if(orient==LEFT){
- var factor=Math.abs(fromX-toX)/2;
- if(factor<CONSTANT)factor=CONSTANT;
- obj.x=array[array.length-1].x-CONSTANT;//replace this with constant!!!
- obj.y=array[array.length-1].y;
- }
- array[array.length]=obj;
- //now check for additional clearance
- if(orient==TOP&&obj.y<toY){//target location is below, we need additional clearance
- var nextObj=new Object();
- if(toX<fromX){
- nextObj.x=toX>((clear[0].x*1)-CONSTANT)?toX:((clear[0].x*1)-CONSTANT);
-
- }
- else{
-
- nextObj.x=toX<((clear[1].x*1)+(CONSTANT*1))?toX:((clear[1].x*1)+(CONSTANT*1));
-
- }
- nextObj.y=obj.y;//fix later
- array[array.length]=nextObj;
- }
- else if(orient==BOTTOM&&obj.y>toY){//target location is, we need additional clearance
- var nextObj=new Object();
- if(toX<fromX){
-
- nextObj.x=toX>((clear[1].x*1)-(CONSTANT*1))?toX:((clear[1].x*1)-(CONSTANT*1));
-
- }
- else{
- nextObj.x=toX<((clear[0].x*1)+(CONSTANT*1))?toX:((clear[0].x*1)+(CONSTANT*1));
-
- }
- nextObj.y=obj.y;//fix later
- array[array.length]=nextObj;
- }
- else if(orient==RIGHT&&obj.x>toX){//target location is left, we need additional clearance
- var nextObj=new Object();
- if(toY<fromY){
- nextObj.y=toY>((clear[0].y*1)-CONSTANT)?toY:((clear[0].y*1)-CONSTANT);
-
- }
- else{
- nextObj.y=toY<((clear[1].y*1)+(CONSTANT*1))?toY:((clear[1].y*1)+(CONSTANT*1));
- }
- nextObj.x=obj.x;//fix later
- array[array.length]=nextObj;
- }
- else if(orient==LEFT&&obj.x<toX){//target location is right, we need additional clearance
- var nextObj=new Object();
-
- if(toY<fromY){
-
- nextObj.y=toY>((clear[1].y*1)-CONSTANT)?toY:((clear[1].y*1)-CONSTANT);
-
- }
- else{
-
- nextObj.y=toY<((clear[0].y*1)+(CONSTANT*1))?toY:((clear[0].y*1)+(CONSTANT*1));
- }
- nextObj.x=obj.x;//fix later
- array[array.length]=nextObj;
- }
- return array;
- }
- /**
- * get the location of the point
- *@param shape
- *@param pointindex
- *@param bounds
- *@return orientation: 0:top,1:right,2:bottom,3:left
- **/
- AbstractRenderer.prototype.getConnectionPointLocation=function(shape,point,bounds){
- var TOP=0;
- var RIGHT=1;
- var BOTTOM=2;
- var LEFT=3;
- var pointNode=shape.getElementsByTagName("connection-point")[point];
- var x=this.getAttribute(pointNode,"x");
- var y=this.getAttribute(pointNode,"y");
- x=(bounds.x*1)+(bounds.width*(x/this.COORD_X));
- y=(bounds.y*1)+(bounds.height*(y/this.COORD_Y));
- if(x<(bounds.x*1+bounds.width/2))return LEFT;
- else if(x>(bounds.x*1)+(bounds.width/2))return RIGHT;
- else if(y<=bounds.y)return TOP;
- else return BOTTOM;
-
-
- }
- /**
- *return the rotated locaction of the shape clearances, clearance will vary by location
- *@param {array}shape bounds
- *@param {int}location 0:top,1:right,2:bottom,3:left
- *@param {int}CONSTANT, how much to add to the clearance
- **/
- AbstractRenderer.prototype.getRotatedClearancePoints=function(bounds,loc,CONSTANT){
- var TOP=0;
- var RIGHT=1;
- var BOTTOM=2;
- var LEFT=3;
- var array=new Array();
- array[array.length]=new Object();
- array[array.length]=new Object();
- if(loc==TOP){
- array[0].x=bounds.x;
- array[0].y=bounds.y;
- array[1].x=(bounds.x*1)+(bounds.width*1);
- array[1].y=bounds.y;
-
- }
- else if(loc==RIGHT){
- array[0].x=(bounds.x*1)+(bounds.width*1);
- array[0].y=bounds.y;
- array[1].x=(bounds.x*1)+(bounds.width*1);
- array[1].y=(bounds.y*1)+(bounds.height*1);
-
- }
- else if(loc==BOTTOM){
- array[0].x=(bounds.x*1)+(bounds.width*1);
- array[0].y=(bounds.y*1)+(bounds.height*1);
- array[1].x=(bounds.x*1);
- array[1].y=(bounds.y*1)+(bounds.height*1);
-
-
- }
- else{
- array[0].x=(bounds.x*1);
- array[0].y=(bounds.y*1)+(bounds.height*1);
- array[1].x=(bounds.x*1);
- array[1].y=(bounds.y*1);
-
-
- }
- return array;//todo rotate these...
- }
- /**
- *check if a line is connected,return the shape id and point
- * @param theline(line/polyline/curve)
- * @param isFrom --are we checking from or to end of the line
- * @return {object} contains shapeid and the point number this line is connected to
- **/
- AbstractRenderer.prototype.getConnectionShape=function(line,isFrom){
- var nodes=line.getElementsByTagName("connection");
- var shapeid="";
- var shapepoint="";
- for(var i=0;i<nodes.length;i++){
- var type=this.getAttribute(nodes[i],"type");
- if(isFrom&&type=='from'){
- shapeid=this.getAttribute(nodes[i],"shapeid");
- shapepoint=this.getAttribute(nodes[i],"shapepoint");
- }
- else if(!isFrom&&type=='to'){
- shapeid=this.getAttribute(nodes[i],"shapeid");
- shapepoint=this.getAttribute(nodes[i],"shapepoint");
- }
-
- }
- var obj=new Object();
- obj.shapeid=shapeid;
- obj.shapepoint=shapepoint;
- return obj;
- }
-
- /**
- *we assume that the shape has already moved,find the connectors attached to a shape and move them to match
- * the current location of the shape connection point they are connected to.
- * @param shape
- **/
- AbstractRenderer.prototype.moveLineWithShape=function(shape){
- //debugger;
- //first get all connections for this shape
- var rect=this.bounds(shape);
- var left=rect['x'];
- var top=rect['y'];
- var width=rect['width'];
- var height=rect['height'];
- var centerX=parseInt(left*1)+parseInt(width/2);
- var centerY=parseInt(top*1)+parseInt(height/2);
- //get the rotation
- var rotation=rect['rotation'];
- if(!rotation)rotation=0;
- //get the shape coordinate size, hardcode for now
- coordX=1000;
- coordY=1000;
- var connectList=shape.getElementsByTagName("connection");
- for(var i=0;i<connectList.length;i++){
- var connection=connectList.item(i);
- var point=connection.parentNode;
- var lineId=connection.getAttribute("lineid");
- var toOrFrom=connection.getAttribute("type");
- //for each connection point get its(unrotated) pixel location
- var conX=(left*1)+((point.getAttribute("x")/this.COORD_X)*width);
- var conY=(top*1)+((point.getAttribute("y")/this.COORD_Y)*height);
- //now translate the center to the origin
- conX=conX-centerX;
- conY=conY-centerY;
- //now rotate and translate back
- var finalX=((conX*Math.cos((Math.PI/180)*(rotation)))-(conY*Math.sin((Math.PI/180)*(rotation)))*1)+(centerX*1);
- var finalY=((conX*Math.sin((Math.PI/180)*(rotation)))+(conY*Math.cos((Math.PI/180)*(rotation)))*1)+(centerY*1);
- if(toOrFrom=="to")
- this.moveLine($(lineId),finalX,finalY,false);
- else
- this.moveLine($(lineId),finalX,finalY,true);
- }
-
- }
- /*
- * return an array of all the connectors attached to the shape
- * @param shape
- * @return array of connectors
- */
- AbstractRenderer.prototype.getAllConnectorsForShape=function(shape){
- if(!shape)return;
- var connectList=shape.getElementsByTagName("connection");
- var array=new Array();
- for(var i=0;i<connectList.length;i++){
- var connection=connectList.item(i);
- var point=connection.parentNode;
- var lineId=connection.getAttribute("lineid");
- if($(lineId))array[array.length]=$(lineId);
- }
- return array;
- }
-
- /**
- *add the connection attribute to the shape and the line
- **/
- AbstractRenderer.prototype.connectLineToShape=function(shape,line,toOrFrom,connectionPoint,pointIndex){
- if(!shape||!line||(pointIndex<0))return;
- var nodeList=line.getElementsByTagName("connection");
- for(var i=0;i<nodeList.length;i++){
- var node=nodeList.item(i);
- var type=node.getAttribute("type");
- if(type==toOrFrom){
- node.setAttribute("shapeid",shape.id);
- node.setAttribute("shapepoint",pointIndex);
- var doc=this.container.ownerDocument;
- var connection=this.createElement("c:connection","CUMULATE_LABS");
- connection.setAttribute("lineid",line.id);
- connection.setAttribute("type",toOrFrom);
- connectionPoint.appendChild(connection);
- }
-
- }
-
- }
- /**
- *disconnect the line i.e null out connection attributes in both the line and shape
- **/
- AbstractRenderer.prototype.disconnectLineFromShape=function(line,toOrFrom){
- //debugger;
- if(!line)return;
- var nodeList=line.getElementsByTagName("connection");
- for(var i=0;i<nodeList.length;i++){
- var node=nodeList.item(i);
- var type=node.getAttribute("type");
- if(type==toOrFrom){
- var shapeId=node.getAttribute("shapeid");
- var point=node.getAttribute("shapepoint");
- if(shapeId&&shapeId.length>0){
- var shape=$(shapeId);
- if(shape){
- setHelp("Disconnected line from shape");
- var connectionPoint=shape.getElementsByTagName("connection-point").item(point*1);
- var connectList=connectionPoint.getElementsByTagName("connection");
- for(var i=0;i<connectList.length;i++){
- var connect=connectList.item(i);
- if((connect.getAttribute("lineid")==line.id)&&(connect.getAttribute("type")==type)){
- this.remove(connect);
- break;
- }
- }
- }
- node.setAttribute("shapeid","xx");
- node.setAttribute("shapepoint","-1");
- }
-
- }
- }
-
- }
-
- /**
- * given the shape bounds return an object with the centerx and y
- * @return {object} with 2 attributes: centerX, centerY
- */
- AbstractRenderer.prototype.getCenterPoint=function(bounds){
- if(bounds){
- var left=bounds.x;
- var top=bounds.y;
- var width=bounds.width;
- var height=bounds.height;
- var obj=new Object();
- obj.centerX=(left*1)+(width/2);
- obj.centerY=(top*1)+(height/2);
- return obj;
- }
-
- }
- /**
- * get rotated point location. Given a point get its rotated location.
- * @param {number}conX
- * @param {number}conY
- * @param bounds array with (x,y,width,height,rotation)
- */
- AbstractRenderer.prototype.getRotatedPoint=function(conX,conY,bounds){
- var rotation=bounds.rotation;
- var center=this.getCenterPoint(bounds);
- var centerX=center.centerX;
- var centerY=center.centerY;
- //now translate the center to the origin
- conX=conX-centerX;
- conY=conY-centerY;
- //now rotate and translate back
- var obj=new Object();
- obj.x=((conX*Math.cos((Math.PI/180)*(rotation)))-(conY*Math.sin((Math.PI/180)*(rotation)))*1)+(centerX*1);
- obj.y=((conX*Math.sin((Math.PI/180)*(rotation)))+(conY*Math.cos((Math.PI/180)*(rotation)))*1)+(centerY*1);
- return obj;
- }
-
- /**
- *To set the text of the shape, we have to do the following
- *1. Get the text box bounds of the selected shape:
- *2. Create a text set i.e break each line by new line token(<br/>) except for the first every text set is of type "newline"
- *3. Calculate the distance between each line, see formula in handleTextPositioning
- *5. Create line shapes for each text set using chars/line i.e divide each text set into line shapes and add to list,for the first
- * line of each textset except new line, the type is "newline"
- *6. Now start from the center of the shape list and draw everything above it and below it
- **/
-
- AbstractRenderer.prototype.setShapeText=function(shape,text,font,isSizeOverride,oldFont,zoomFactor/**zoom is only used for font**/){
-
- var shapeFont=oldFont;
- if(!shapeFont)
- shapeFont=this.getFont(shape);
- //now lets fill in whats not available
- if(shapeFont.size==''||isSizeOverride){
- shapeFont.size=font.size;
-
- }
- if(shapeFont.color==''){
- shapeFont.color=font.color;
- }
- if(shapeFont.family==''){
- shapeFont.family=font.family;
- }
- if(shapeFont.align==''){
- shapeFont.align=font.align;
- }
- if(shapeFont.bold==''){
- shapeFont.bold=font.bold;
- }
- if(shapeFont.italics==''){
- shapeFont.italics=font.italics;
- }
-
- /**we need to preserve this so that whenever the shape is moved,it is used**/
- var actualShapeFontSize=shapeFont.size;
- var fontSize=shapeFont.size*zoomFactor;
- shapeFont.size=fontSize;
-
- var rect=this.getTextBounds(shape,text,zoomFactor,shapeFont);
-
- var width=rect["width"];
- var height=rect["height"];
- var x=rect['x'];
- var y=rect['y'];
- if(width<25){
- width=25;
- }
- if(height==0){
- height=1;
- }
- //chars per line
- var cpl=((width/fontSize))*2;
- cpl=Math.ceil(cpl);
- //wrap the text, false indicates--break the line if larger than cpl
- var wrappedText=text.wordWrap(cpl,this.LINE_DELIMITER,false);
- var textArray=this.createTextSet(wrappedText);
- if(textArray.length==0){
- return false;
- }
- var lines=this.createLines(textArray,cpl);
- var lineCenter=Math.ceil(lines.length/2);
- var shapeArray=null;
- //ie has different algorithms for text line positioning for shapes and lines
- if(this.isConnector(shape)){
- shapeArray=this.handleConnectorTextLinePositioning(height,width,x,y,lineCenter,fontSize,lines,shapeFont,shape);
-
- }
- else{
- shapeArray=this.handleTextLinePositioning(height,width,x,y,lineCenter,fontSize,lines,shapeFont,shape);
- }
- //finally create a dummy shape to put all the text in
- //debugger;
- var dummyLine=new Object();
- dummyLine.type=shape.id;
- dummyLine.text="";
- shapeFont.size=actualShapeFontSize;
- shapeArray[shapeArray.length]=this.createTextShape(dummyLine,false,0,0,0,0,shapeFont,shape);
- if(this.isConnector(shape)){
- this.handleConnectorTextBackgroundPositioning(shape,rect,text);
- }
- //now add all the shapes to the shape
- for(var i=0;i<shapeArray.length;i++){
- shape.appendChild(shapeArray[i]);
-
- }
- var textData=this.setTextData(shape,text);
- }
-
- /**
- * create the background rect element, this is the background shape for connector text
- * @param the connector shape
- */
- AbstractRenderer.prototype.getConnectorBackgroundShape=function(shape){
- var bgShape=null;
- if(shape.getElementsByTagName("rect").length>0)
- bgShape=shape.getElementsByTagName("rect")[0];
- else{
- bgShape=this.createElement("rect",this.VML_SVG_NAMESPACE);
- bgShape.style.position='absolute';
- this.setFillColor(shape,"white");
- this.setOpacity(shape,"1.0");
- var subject=this.getShapeSubject(shape);
- bgShape.style.zIndex=subject.style.zIndex;
- //else
- //bgShape.style.zIndex=this.maxIndex;
- this.setStrokeWidth(bgShape,"0px");
-
- }
- return bgShape;
- }
-
- /**
- * starting version 0.3.7, the text will be stored in a comment field inside the c:textData element, this is done
- * for optimization purposes and because newlines were being lost by placing the text in attributes, In
- * addition the text will be htmlEncoded to prevent invalid xml
- */
- AbstractRenderer.prototype.setTextData=function(shape,text){
-
- if(!text)text="";
- //first clean up existing nodes
- var nodes=shape.getElementsByTagName("textData");
- var nodeArray=$A(nodes);
- for(var i=0;i<nodeArray.length;i++){
- var node=nodeArray[i];
- this.remove(node);
- }
- var textData=this.createElement("c:textData","CUMULATE_LABS");
- var textNode=this.container.ownerDocument.createComment(JH.Utilities.HtmlEncode2(text));
- textData.appendChild(textNode);
- textData.setAttribute("version","0.3.7");
- shape.appendChild(textData);
-
-
-
- }
- /**
- * starting version 0.3.6, the text will be stored in a comment field inside the c:textData element, this is done
- * for optimization purposes and because newlines were being lost by placing the text in attributes
- * Update:since 0.3.7 we are placing encoded html text instead of just escaped one...
- */
- AbstractRenderer.prototype.getShapeText=function (shape,otherDoc){
- //this is pre 0.3.2, we will eventually remove this
- var element=document.getElementById("text:dummy"+shape.id);
- //for pre 0.3.6
- if(element){
- return this.getShapeTextDeprecated(shape,otherDoc);
- }
- var nodes=shape.getElementsByTagName("textData");
- var version=null;
- if(nodes.length>0)
- version=nodes[0].getAttribute("version");
- if(nodes.length==0||version==null||version==""){
- return this.getShapeTextDeprecated(shape,otherDoc);
- }
- else {
- var comment=nodes[0].firstChild;
- if(comment==null)return "";
- var text=comment.nodeValue;
- if(version=="0.3.6"){
- text=unescape(text);
- }
- else{//since 0.3.7 we are placing encoded html text instead of just escaped one...
- text=JH.Utilities.HtmlDecode2(text);
- }
- return text;
- }
-
- }
- /**
- *this method will return the actual text of the shape which has been hidden in a dummy shape
- */
- AbstractRenderer.prototype.getShapeTextDeprecated=function(shape,otherDoc){
-
- if(!shape){
- return null;
- }
- //we keep this for backward compatibility...we are not going to use this
- //starting 0.3, we use c:textData elements to store data
- var element=document.getElementById("text:dummy"+shape.id);
- if(element) return element.string;
- //this is how post 0.2 implementations will handle text data
- else{
- var string="";
- var nodes=shape.getElementsByTagName("textData");
- for(var i=0;i<nodes.length;i++){
- string+=nodes[i].getAttribute("string");
-
- }
- return string;
- }
-
- }
-
- /**
- *create the lines
- *@param array of lines
- *@param characters for line
- */
- AbstractRenderer.prototype.createLines=function(textArray,charsPerLine){
- var lineArray=new Array();
- for(var i=0;i<textArray.length;i++){
- var stringVal=textArray[i];
- if(stringVal.length<charsPerLine){
- var lineObj=new Object();
- lineObj.text=stringVal;
- lineObj.type="normal";
- lineArray[lineArray.length]=lineObj;
- }
- else{
- var numlines=Math.floor((stringVal.length/charsPerLine));
- var remainder=stringVal.length%charsPerLine;
- var j=0;
- for(j=0;j<numlines;j++){
- var line=stringVal.substr((j*charsPerLine),charsPerLine);
- var lineObj=new Object();
- lineObj.text=line;
- if(j==0){
- lineObj.type="newline";
- }
- else{
- lineObj.type="normal";
- }
- lineArray[lineArray.length]=lineObj;
- }
- if(remainder>0){
- var line=stringVal.substr((j*charsPerLine),remainder);
- var lineObj=new Object();
- lineObj.text=line;
- if(numlines==0){
- lineObj.type="newline";
- }
- else{
- lineObj.type="normal";
- }
- lineArray[lineArray.length]=lineObj;
- }
- }
-
- }
- return lineArray;
-
- }
-
- /**
- * for shapes, return the text bounds if it exists, otherwise return the dimensions of the shape. For connectors
- * return the text width and height (or reasonable default) anchored around the center point
- * @param shape
- * @param connectorText (optional)--only passed for connectors
- * @param current zoom factor
- */
- AbstractRenderer.prototype.getTextBounds=function(shape, connectorText,zoomFactor,font){
- if(this.isConnector(shape)){
- var center=this.getConnectorCenterPoint(shape);
- var textSize=this.getConnectorTextSize(shape,connectorText,zoomFactor,font);
- var bounds=new Object();
- bounds.width=textSize.width;
- bounds.height=textSize.height;
- bounds.x=(center.x-bounds.width/2);
- bounds.y=(center.y-bounds.height/2);
- return bounds;
- }
- else{
- var rect=this.bounds(shape);
- var textBounds=shape.getElementsByTagName("text-bound");
- if(textBounds.length==0)return rect;
- else{
- var bounds=rect;
- var textb=textBounds[0];
- var x=this.getAttribute(textb,"fromX");
- var y=this.getAttribute(textb,"fromY");
- var x2=this.getAttribute(textb,"toX");
- var y2=this.getAttribute(textb,"toY");
- var newX=(x*bounds.width/1000)+(bounds.x*1);
- var newY=(y*bounds.height/1000)+(bounds.y*1);
- var width=(x2-x)*(bounds.width/1000);
- var height=(y2-y)*(bounds.height/1000)
- bounds.x=bounds.left=newX;
- bounds.y=bounds.top=newY;
- var textSize=this.getConnectorTextSize(shape,connectorText,zoomFactor,font);
- bounds.width=textSize.width;
- bounds.height=textSize.height;
- return bounds;
- }
- }
- }
- /**
- *break the text up by new lines \n, called from setShapeText
- */
- AbstractRenderer.prototype.createTextSet=function(text){
- var textArray=new Array();
- if(!text||text.length==0){
- return textArray;
- }
- else{
- textArray=text.split(this.LINE_DELIMITER);
- return textArray;
- }
- }
-
- /**
- *Intialize an empty font object with the remaining default attributes (besides the one already populated)
- * this way we don't have to poulate defaults everywhere a font is used.
- * @param a partially filled font object
- **/
-
- AbstractRenderer.prototype.fillUpFont=function(font){
- if(font.size=='')
- font.size=16;
- if(font.family=='')
- font.family="'arial'";
- if(font.italics=='')
- font.italics="normal";
- if(font.bold=='')
- font.bold="normal"
- if(font.align=='')
- font.align="center";
- if(font.color=='')
- font.color="black";
-
-
- }
-